package com.luo.demo.scg.client.config;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.security.config.web.server.ServerHttpSecurity;
import org.springframework.security.web.server.SecurityWebFilterChain;
import org.springframework.security.web.server.util.matcher.ServerWebExchangeMatcher;
import org.springframework.security.web.server.util.matcher.ServerWebExchangeMatchers;

/**
 * SpringSecurity OAuth2 Resource Server配置
 *
 * @author luohq
 * @version 1.0.0
 * @date 2022-02-21 10:14
 */
@Configuration
public class ResourceApiSecurityConfig {

    /**
     * 需要进行OAuth2 Resource验证的API模式列表
     */
    @Value("${spring.security.oauth2.resourceserver.api-path-mvc-patterns}")
    private String[] apiPathMvcPatterns;

    @Bean
    @Profile("oauth2-resource-server-jwt")
    SecurityWebFilterChain jwtResourceApiSecurityFilterChain(ServerHttpSecurity http, ResourceApiAuthorizationManager resourceApiAuthorizationManager) throws Exception {
        http
                //设置request matcher(仅针对需要进行OAuth Resource验证的API进行拦截)
                .securityMatcher(this.buildExchangeMatcher())
                ////禁用csrf防御（避免post请求被拦截）
                .csrf().disable()
                ////session管理
                //.sessionManagement(session -> session
                //        //无状态session（即不使用session，避免创建session 及 使用session存储Authentication信息进而绕过验证）
                //        .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                //)

                //授权设置
                .authorizeExchange(authorize -> authorize
                        //集成自定义验证器
                        .anyExchange().access(resourceApiAuthorizationManager)
                )
                //启用JWT验证
                .oauth2ResourceServer(ServerHttpSecurity.OAuth2ResourceServerSpec::jwt);
        return http.build();
    }

    @Bean
    @Profile("oauth2-resource-server-opaque")
    SecurityWebFilterChain opaqueResourceApiSecurityFilterChain(ServerHttpSecurity http, ResourceApiAuthorizationManager resourceApiAuthorizationManager) throws Exception {
        http
                //设置request matcher(仅针对需要进行OAuth Resource验证的API进行拦截)
                .securityMatcher(this.buildExchangeMatcher())
                ////禁用csrf防御（避免post请求被拦截）
                .csrf().disable()
                ////session管理
                //.sessionManagement(session -> session
                //        //无状态session（即不使用session，避免创建session 及 使用session存储Authentication信息进而绕过验证）
                //        .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                //)

                //授权设置
                .authorizeExchange(authorize -> authorize
                        //集成自定义验证器
                        .anyExchange().access(resourceApiAuthorizationManager)
                )
                //启用OpaqueToken验证
                .oauth2ResourceServer(ServerHttpSecurity.OAuth2ResourceServerSpec::opaqueToken);
        return http.build();
    }

    /**
     * 构建请求匹配器
     *
     * @return 请求匹配器
     */
    private ServerWebExchangeMatcher buildExchangeMatcher() {
        if (null == apiPathMvcPatterns || 0 >= apiPathMvcPatterns.length) {
            return ServerWebExchangeMatchers.anyExchange();
        }
        return ServerWebExchangeMatchers.pathMatchers(this.apiPathMvcPatterns);
    }
}
